package cuongnh.project.japanesediary.vocabulary.ui.dialog;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.model.Kanji;
import cuongnh.project.japanesediary.vocabulary.ui.common.composite.SearchComposite;
import cuongnh.project.japanesediary.vocabulary.ui.wizard.AddKanjiWizard;

public class AddRelatedKanjiDialog extends Dialog {

	private TableViewer tblvKanjiList;

	private SearchComposite search;
	private CommonServices commonServices;
	private List<Kanji> kanjis;
	private Set<Kanji> selectedKanjis;

	/**
	 * Create the dialog.
	 * 
	 * @param parentShell
	 */
	public AddRelatedKanjiDialog(Shell parentShell,
			CommonServices commonServices) {
		super(parentShell);
		setShellStyle(SWT.MAX | SWT.RESIZE);
		this.commonServices = commonServices;
	}

	public void initData() {
		kanjis = (commonServices.getKanjiDao() != null) ? commonServices
				.getKanjiDao().getAll() : Collections.<Kanji> emptyList();
	}

	/**
	 * Create contents of the dialog.
	 * 
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite container = (Composite) super.createDialogArea(parent);
		container.setLayout(new GridLayout(2, false));
		// Search control
		search = new SearchComposite(container);
		search.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1,
				1));

		Button btnNew = new Button(container, SWT.NONE);
		btnNew.setText("New...");
		btnNew.addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				Kanji newKanji = new Kanji();
				AddKanjiWizard newKanjiWizard = new AddKanjiWizard(
						commonServices, newKanji);
				WizardDialog dialog = new WizardDialog(getShell(),
						newKanjiWizard);
				if (dialog.open() == Window.OK) {
					kanjis.add(newKanji);
					selectedKanjis.add(newKanji);
					tblvKanjiList.refresh();
					tblvKanjiList
							.setSelection(new StructuredSelection(newKanji));
				}
			}
		});

		// Separate composite to embed the table
		Composite tableComposite = new Composite(container, SWT.NONE);
		tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 2, 1));

		tblvKanjiList = new TableViewer(tableComposite, SWT.BORDER
				| SWT.FULL_SELECTION | SWT.MULTI);

		Table tblKanjis = tblvKanjiList.getTable();
		tblKanjis.setHeaderVisible(true);
		tblKanjis.setLinesVisible(true);
		tblKanjis.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1));

		TableViewerColumn tbclvKanji = new TableViewerColumn(tblvKanjiList,
				SWT.NONE);
		TableColumn tblclmnKanji = tbclvKanji.getColumn();
		tblclmnKanji.setWidth(100);
		tblclmnKanji.setText("Kanji");

		TableViewerColumn tbclvOnyomi = new TableViewerColumn(tblvKanjiList,
				SWT.NONE);
		TableColumn tblclmnOnyomi = tbclvOnyomi.getColumn();
		tblclmnOnyomi.setWidth(100);
		tblclmnOnyomi.setText("Onyomi");

		TableViewerColumn tbclvKunyomi = new TableViewerColumn(tblvKanjiList,
				SWT.NONE);
		TableColumn tblclmnKunyomi = tbclvKunyomi.getColumn();
		tblclmnKunyomi.setWidth(100);
		tblclmnKunyomi.setText("Kunyomi");

		TableViewerColumn tbclvHanviet = new TableViewerColumn(tblvKanjiList,
				SWT.NONE);
		TableColumn tblclmnHanviet = tbclvHanviet.getColumn();
		tblclmnHanviet.setWidth(100);
		tblclmnHanviet.setText("HAN-VIET");

		TableViewerColumn tbclvVnMeaning = new TableViewerColumn(tblvKanjiList,
				SWT.NONE);
		TableColumn tblclmnVnMeaning = tbclvVnMeaning.getColumn();
		tblclmnVnMeaning.setWidth(100);
		tblclmnVnMeaning.setText("Vietnamese meaning");

		// Specify column's width by a percentage
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnKanji, new ColumnWeightData(7,
				true));
		tblColumnLayout.setColumnData(tblclmnOnyomi, new ColumnWeightData(15,
				true));
		tblColumnLayout.setColumnData(tblclmnKunyomi, new ColumnWeightData(15,
				true));
		tblColumnLayout.setColumnData(tblclmnHanviet, new ColumnWeightData(10,
				true));
		tblColumnLayout.setColumnData(tblclmnVnMeaning, new ColumnWeightData(
				45, true));
		tableComposite.setLayout(tblColumnLayout);

		// Filter
		tblvKanjiList.addFilter(new ViewerFilter() {

			@Override
			public boolean select(Viewer viewer, Object parentElement,
					Object element) {
				Kanji kanji = (Kanji) element;
				String text = String.valueOf(search.observeText().getValue());
				if (kanji.getKanji().toLowerCase().contains(text.toLowerCase())) {
					return true;
				}

				return false;
			}

		});

		search.observeText().addChangeListener(
				new org.eclipse.core.databinding.observable.IChangeListener() {
					@Override
					public void handleChange(
							org.eclipse.core.databinding.observable.ChangeEvent event) {
						tblvKanjiList.refresh();
					}
				});

		initData();
		initDataBindings();
		return container;
	}

	/**
	 * Create contents of the button bar.
	 * 
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
				true);
		createButton(parent, IDialogConstants.CANCEL_ID,
				IDialogConstants.CANCEL_LABEL, false);
	}

	/**
	 * Return the initial size of the dialog.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(671, 700);
	}

	@Override
	protected void okPressed() {
		selectedKanjis = new HashSet<Kanji>();
		StructuredSelection sel = (StructuredSelection) tblvKanjiList
				.getSelection();
		for (Iterator<Kanji> iter = sel.iterator(); iter.hasNext();) {
			selectedKanjis.add(iter.next());
		}
		close();
	}

	public Set<Kanji> getSelectedKanjis() {
		return selectedKanjis;
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				listContentProvider.getKnownElements(), Kanji.class,
				new String[] { "kanji", "onyomi", "kunyomi", "hanviet",
						"vnMeaning" });
		tblvKanjiList.setLabelProvider(new ObservableMapLabelProvider(
				observeMaps));
		tblvKanjiList.setContentProvider(listContentProvider);
		//
		IObservableList selfList = Properties.selfList(Kanji.class).observe(
				kanjis);
		tblvKanjiList.setInput(selfList);
		//
		return bindingContext;
	}
}
